package com.supor.aiot.common.ui.view.skeleton;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.supor.aiot.common.R;

public class SkeletonFrameLayout extends FrameLayout {
  private final Paint mContentPaint = new Paint();
  private final SkeletonDrawable mSkeletonDrawable = new SkeletonDrawable();

  private boolean mShowShimmer = true;
  private boolean mStoppedShimmerBecauseVisibility = false;

  public SkeletonFrameLayout(Context context) {
    super(context);
    init(context, null);
  }

  public SkeletonFrameLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
  }

  public SkeletonFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs);
  }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public SkeletonFrameLayout(
      Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init(context, attrs);
  }

  private void init(Context context, @Nullable AttributeSet attrs) {
    setWillNotDraw(false);
    mSkeletonDrawable.setCallback(this);

    if (attrs == null) {
      setShimmer(new Skeleton.AlphaHighlightBuilder().build());
      return;
    }

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShimmerFrameLayout, 0, 0);
    try {
      Skeleton.Builder shimmerBuilder =
          a.hasValue(R.styleable.ShimmerFrameLayout_shimmer_colored)
                  && a.getBoolean(R.styleable.ShimmerFrameLayout_shimmer_colored, false)
              ? new Skeleton.ColorHighlightBuilder()
              : new Skeleton.AlphaHighlightBuilder();
      setShimmer(shimmerBuilder.consumeAttributes(a).build());
    } finally {
      a.recycle();
    }
  }

  public SkeletonFrameLayout setShimmer(@Nullable Skeleton skeleton) {
    mSkeletonDrawable.setShimmer(skeleton);
    if (skeleton != null && skeleton.clipToChildren) {
      setLayerType(LAYER_TYPE_HARDWARE, mContentPaint);
    } else {
      setLayerType(LAYER_TYPE_NONE, null);
    }

    return this;
  }

  public @Nullable
  Skeleton getShimmer() {
    return mSkeletonDrawable.getShimmer();
  }

  public void startShimmer() {
    mSkeletonDrawable.startShimmer();
  }

  public void stopShimmer() {
    mStoppedShimmerBecauseVisibility = false;
    mSkeletonDrawable.stopShimmer();
  }

  public boolean isShimmerStarted() {
    return mSkeletonDrawable.isShimmerStarted();
  }

  public void showShimmer(boolean startShimmer) {
    mShowShimmer = true;
    if (startShimmer) {
      startShimmer();
    }
    invalidate();
  }

  public void hideShimmer() {
    stopShimmer();
    mShowShimmer = false;
    invalidate();
  }

  public boolean isShimmerVisible() {
    return mShowShimmer;
  }

  @Override
  public void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    final int width = getWidth();
    final int height = getHeight();
    mSkeletonDrawable.setBounds(0, 0, width, height);
  }

  @Override
  protected void onVisibilityChanged(View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    // View's constructor directly invokes this method, in which case no fields on
    // this class have been fully initialized yet.
    if (mSkeletonDrawable == null) {
      return;
    }
    if (visibility != View.VISIBLE) {
      // GONE or INVISIBLE
      if (isShimmerStarted()) {
        stopShimmer();
        mStoppedShimmerBecauseVisibility = true;
      }
    } else if (mStoppedShimmerBecauseVisibility) {
      mSkeletonDrawable.maybeStartShimmer();
      mStoppedShimmerBecauseVisibility = false;
    }
  }

  @Override
  public void onAttachedToWindow() {
    super.onAttachedToWindow();
    mSkeletonDrawable.maybeStartShimmer();
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    stopShimmer();
  }

  @Override
  public void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    if (mShowShimmer) {
      mSkeletonDrawable.draw(canvas);
    }
  }

  @Override
  protected boolean verifyDrawable(@NonNull Drawable who) {
    return super.verifyDrawable(who) || who == mSkeletonDrawable;
  }
}
